package gbench.mydata.driver.core.data;

import java.sql.SQLException;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

import gbench.common.matlib.MatlibCanvas.XVec;
import gbench.common.tree.LittleTree;
import gbench.common.tree.LittleTree.IRecord;

/**
 * 数据列表： 数据列表 有三个 说因字段： <br>
 * 
 * [index_of_before_first,index_of_current,index_of_after_last], 通过 这个 三个 字段
 * 定义出了一点 active 的 数据区段。
 * 
 * @author gbench
 *
 */
public abstract class DataBuffer {

    /**
     * 数据初始化
     * 
     * @param index_of_before_first
     * @param index_of_after_last
     * @param index_of_current
     * @param current
     * @param metadata
     * @param dataset
     * @return
     */
    public DataBuffer initialize(int index_of_before_first, int index_of_after_last, int index_of_current,
            IRecord current, IRecord metadata, List<IRecord> dataset) {
        this.dataset(this.dataset);
        this.index_of_after_last(index_of_after_last);
        this.index_of_before_first(index_of_before_first);
        this.index_of_current(index_of_current);
        this.metadata(this.metadata);
        this.refresh();
        return this;
    }

    /**
     * 数据初始化
     * 
     * @param index_of_before_first
     * @param index_of_after_last
     * @param index_of_current
     * @param current
     * @param metadata
     * @param dataset
     * @return
     */
    public DataBuffer initialize(final DataBuffer dataBuffer) {
        this.dataset(dataBuffer.dataset());
        this.index_of_after_last(dataBuffer.index_of_after_last());
        this.index_of_before_first(dataBuffer.index_of_before_first());
        this.index_of_current(dataBuffer.index_of_current);
        this.metadata(dataBuffer.metadata);
        this.refresh();
        return this;
    }

    /**
     * 
     */
    @Override
    public DataBuffer clone() {
        final var dataBuffer = new DataBuffer() {
        }; // 新生成一个 dataBuffer
        return dataBuffer.initialize(this);
    }

    /**
     * 数据尺寸
     * 
     * @return 数据条目数量
     */
    public int size() {
        return this.dataset.size();
    }

    /**
     * 数据重置:this.reset(-1) 的简写
     */
    public DataBuffer reset() {
        this.reset(-1);
        return this;
    }

    /**
     * 数据重置
     */
    public DataBuffer reset(int index_of_before_first) {
        this.index_of_before_first = index_of_before_first;
        this.index_of_current = this.index_of_before_first;
        this.current = null;

        if (this.dataset != null) { // 清空
            this.metadata = dataset.get(0);
            final var index_of_first = (this.index_of_before_first + 1); // 第一项的偏移地址
            this.index_of_after_last(index_of_first + this.size());
        } // if
        return this;
    }

    /**
     * 设置 index_of_current, 定位到 第 i 个 偏移地址, 这是 所有 移动 cursor 的 最终 实现函数。
     * 
     * @param i        待要设置的偏移位置，index_of_current 的 有效范围 为 [ -1, this.size() ],<br>
     *                 其中: <br>
     *                 -1 表示 beforeFirst <br>
     *                 0 表示 first <br>
     *                 this.size()-1 表示 last <br>
     *                 this.size() 表示 afterLast <br>
     * @param 重定位后的结果值
     */
    public IRecord relocate(final int i) {

        final var n = this.size();
        if (i >= -1 && i <= n) { // 合法部分 偏移值 接收 偏移 并 读取（设置） 当前 记录值
            this.index_of_current = i; // 设置 偏移值
            this.current = i == -1 || i == n // 检测是否 刚好 位于 边界位置:即 beforeFirst 或 afterLast
                    ? null // 边界位置 设置 current 为 null
                    : dataset.get(this.index_of_current); // 设置偏移获取当前节点
        } else { // 非法部分 偏移值 不予处理
            System.err.println("非法index_of_current" + i);
            System.err.println("非法index_of_current" + Arrays.stream(Thread.currentThread().getStackTrace())
                    .map(Object::toString).collect(Collectors.joining("\n")));
        } // if

        return this.current;
    }

    /**
     * 获取键名字段的索引号
     * 
     * @param name 名称
     * @return 列名索引 从 1 开始, 非法值 返回 -1
     */
    public int name2columnIndex(final String name) {

        if (this.current == null) {
            return -1;
        }

        return this.current.key2idx(name) + 1;
    }

    /**
     * 字段的索引下标转字段名称
     * 
     * idx 索引序号从1开始
     * 
     * @return 列名索引
     */
    public String columnIndex2name(final int idx) {

        if (this.current == null) {
            return null;
        }

        return this.current.idx2key(idx - 1);
    }

    /**
     * 返回当前的记录值（缓存的当前数据记录）
     * 
     * @return （缓存的当前数据记录）
     */
    public IRecord current() {
        return this.current;
    }

    /**
     * 重新计算当前记录的值
     * 
     * @return 重新计算当前记录的值
     */
    public IRecord refresh() {
        if (this.index_of_current > this.index_of_before_first && this.index_of_current < this.index_of_after_last) {
            return this.current = this.dataset.get(this.index_of_current);
        } else {
            return this.current = null;
        }
    }

    /**
     * 计算 row 的偏移地址<br>
     * 计算逻辑相当于 this.index_of_before_first() + row;
     * 
     * @param row 大于等于1的整数
     * @return 计算 row 的偏移地址
     */
    public int index_of_row(int row) {
        return this.index_of_before_first() + row;
    }

    public int index_of_first() {
        return this.index_of_before_first + 1;
    }

    public int index_of_last() {
        return this.index_of_after_last - 1;
    }

    public int index_of_previous() {
        return this.index_of_relative(-1);
    }

    public int index_of_next() {
        return this.index_of_relative(1);
    }

    /**
     * 索引的相对移动
     * 
     * @param n 相对距离：负数 向前， 正数 向后
     * @return 相对移动后的 新的索引位置
     */
    public int index_of_relative(int n) {
        return this.index_of_current() + n;
    }

    /**
     * 
     * @return index_of_before_first
     */
    public int index_of_before_first() {
        return index_of_before_first;
    }

    /**
     * 
     * @return index_of_before_first
     */
    public int index_of_before_first(int index_of_before_first) {
        return this.index_of_before_first = index_of_before_first;
    }

    /**
     * 
     * @return index_of_after_last
     */
    public int index_of_after_last() {
        return index_of_after_last;
    }

    /**
     * 
     * @return index_of_after_last
     */
    public int index_of_after_last(int index_of_after_last) {
        return this.index_of_after_last = index_of_after_last;
    }

    /**
     * 
     * @return index_of_current
     */
    public int index_of_current() {
        return this.index_of_current;
    }

    /**
     * 
     * @return index_of_current
     */
    public int index_of_current(int index_of_current) {
        return this.index_of_current = index_of_current;
    }

    /**
     * 
     * @return metadata
     */
    public IRecord metadata() {
        return this.metadata;
    }

    /**
     * 
     * @return metadata
     */
    public IRecord metadata(IRecord metadata) {
        return this.metadata = metadata;
    }

    /**
     * 
     * @return dataset
     */
    public List<IRecord> dataset() {
        return this.dataset;
    }

    /**
     * 
     * @return dataset
     */
    public List<IRecord> dataset(List<IRecord> dataset) {
        return this.dataset = dataset;
    }

    /**
     * 在当前位置之后 处于 iterable 数量的新的元素
     * 
     * @param iterable
     * @return this 对象本身便于实现链式编程
     */
    public DataBuffer insert(final Iterable<IRecord> iterable) {
        return this.insert(this.index_of_next(), iterable);
    }

    /**
     * index_of_current 保持不变 <br>
     * 在 i 处 插入 ll 个数据元素 位置i被替换成 iterable 的第一个元素，原来的元素 被推移到 i+ sizeof(iterable)
     * 
     * @param i        待出入位置，i 大于等于index_of_first的整数 且 小于 this.index_of_after_last 即
     *                 [index_of_first,index_of_after_last]
     * @param iterable 待插入的数据
     * @return this 对象本身便于实现链式编程
     */
    public DataBuffer insert(int i, final Iterable<IRecord> iterable) {
        if (iterable != null && i >= this.index_of_first() && i <= this.index_of_after_last()) {
            final var aa = LittleTree.iterable2list(iterable).toArray(IRecord[]::new);
            final int n = aa.length; // 匀速数组大小
            this.index_of_after_last += n;
            this.dataset = XVec.OF(this.dataset).insert(i, aa).list();
            this.refresh(); // 刷新当前数值
        }
        return this;
    }

    /**
     * 新增加元素
     * 
     * @param iterable 新增加的元素
     * @return this 对象本身便于实现链式编程
     */
    public synchronized DataBuffer append(final Iterable<IRecord> iterable) {

        if (iterable != null) { // 添加数据合法 有效
            final Collection<IRecord> ll = iterable instanceof Collection // 是否直接就是可遍历对象
                    ? (Collection<IRecord>) iterable // 原来的 类型
                    : LittleTree.iterable2list(iterable); // 可以遍历的集合
            int n = ll.size();
            this.dataset().addAll(ll); // 补充新元素
            this.index_of_after_last(this.index_of_after_last + n);
            this.refresh();
        } // if

        return this;
    }

    /**
     * 去除头前的 n 个元素 <br>
     * 当前值的 变换逻辑为： <br>
     * this.index_of_current = this.index_of_current < n ? -1 :
     * this.index_of_current - n; <br>
     * 
     * @param n>0 去除头前的 n 个元素 反之 去除 尾部 n 个元素
     * @return this 对象本身便于实现链式编程
     */
    public DataBuffer drop(int n) {
        if (n > 0) { // 从 头部 删除
            this.drop_at_head(n);
        } else { // 从 尾部删除
            this.drop_at_tail(-n);
        }
        return this;
    }

    /**
     * 删除一个区间 [from,to)
     * 
     * @param from 开始位置索引，从 0开始，包含
     * @param to   结束位置，从 0开始，不包含
     * @return this 对象本身便于实现链式编程
     */
    public DataBuffer drop(int from, int to) {

        final var _from = Math.max(this.index_of_before_first, from); // 调整 开始索引
        final var _to = Math.min(this.index_of_after_last, to); // 调整 结尾索引

        if (_from < _to && _from >= this.index_of_before_first && _to <= this.index_of_after_last()) { // 删除范围有效
            final int n = _to - _from; // 删除的元素的长度
            if (_to < this.index_of_current) { // 在前头删除 n 个元素
                this.index_of_after_last = this.index_of_after_last - n; // 从后头删除 n 个元素
                this.index_of_current = this.index_of_current - n;
            } else if (_from > this.index_of_current) { // 在后头删除 n 个元素, 对 this.index_of_current 没有影响
                this.index_of_after_last = this.index_of_after_last - n;
            } else { // 前后都有删除, 前头删除 this.index_of_current - from 个元素, this.index_of_current 调整为
                     // from+1
                this.index_of_after_last = this.index_of_after_last - n;
                this.index_of_current = from + 1 < this.index_of_after_last ? from + 1 : this.index_of_after_last;
            } // if
            this.dataset = XVec.OF(this.dataset).delete(from, to).list(); // 把 from,to 之间的元素给予剔除
            this.refresh(); // 重新计算新的当前记录
        } // if

        return this;
    }

    /**
     * 去除头前的 n 个元素 <br>
     * 当前值的 变换逻辑为： <br>
     * this.index_of_current = this.index_of_current < n ? -1 :
     * this.index_of_current - n; <br>
     * 
     * @param n 去除头前的 n 个元素 ， 大于 0 且 小于 this.size() 的整数
     * @return this 对象本身便于实现链式编程
     */
    public DataBuffer drop_at_head(int n) {

        if (n > 0 && n <= this.size()) {
            this.index_of_after_last -= n;
            this.index_of_current = this.index_of_current < n ? -1 : this.index_of_current - n;
            this.dataset = this.dataset.subList(n, this.size());
            this.refresh();
        } // if

        return this;
    }

    /**
     * 去除尾部 的 n 个元素 <br>
     * 
     * @param n 去除尾部 的 n 个元素 ， 大于 0 且 小于 this.size() 的整数
     * @return this 对象本身便于实现链式编程
     */
    public DataBuffer drop_at_tail(int n) {

        if (n > 0 && n <= this.size()) {
            this.index_of_after_last -= n;
            this.index_of_current = this.index_of_current > this.index_of_after_last ? this.index_of_after_last
                    : this.index_of_current;
            this.dataset = this.dataset.subList(0, this.size() - n);
            this.refresh();
        } // if

        return this;
    }

    /**
     * 连接两个 DataBuffer
     * 
     * @param dataBuffer 另一个 dataBuffer
     * @return 新生成的一个新的 dataBuffer
     * @return 新生成的一个DataBuffer 有 [this,dataBuffer]进行收尾相连
     */
    public DataBuffer concat(final DataBuffer dataBuffer) {
        return this.clone().insert(this.index_of_after_last, dataBuffer.dataset());
    }

    /**
     * 是否唯一第一行前
     * 
     * @return
     */
    public boolean ops_is_before_first() {
        return this.index_of_current() <= this.index_of_before_first();
    }

    /**
     * 是否位于最后一行后
     * 
     * @return
     */
    public boolean ops_is_after_last() {
        return this.index_of_current() >= this.index_of_after_last();
    }

    /**
     * 是否是第一行
     * 
     * @return
     * @throws SQLException
     */
    public boolean ops_is_first() throws SQLException {
        return this.index_of_current() == this.index_of_first();
    }

    /**
     * 是否是最后一行
     * 
     * @return
     */
    public boolean ops_is_last() {
        return this.index_of_current() == this.index_of_last();
    }

    /**
     * 移动到第一行以前
     */
    public void ops_before_first() {
        this.relocate(this.index_of_before_first());
    }

    /**
     * 移动到最后一航以后
     */
    public void ops_after_last() {
        this.relocate(this.size());
    }

    /**
     * 移动到第一行
     * 
     * @return
     */
    public boolean ops_first() {
        this.relocate(this.index_of_first());
        return this.index_of_current() == this.index_of_first();
    }

    /**
     * 移动最后一行
     * 
     * @return
     */
    public boolean ops_last() {
        this.relocate(this.index_of_last());
        return this.index_of_current() == this.index_of_last();
    }

    /**
     * 移动到 第 row 行
     * 
     * @param row 行号 大于等于1 且 小于等于 last_row 的整数
     * @return
     */
    public boolean ops_absolute(int row) {
        // 有效的行号区间为[ 1 , last_row ], 其他一切都是非法的
        int last_row = this.index_of_last() - this.index_of_before_first();
        if (row >= 1 && row <= last_row) { // 行号的有效性 检测
            int i = this.index_of_row(row); // 获取row的偏移地址
            this.relocate(i); // 重定位
            return true;
        } else { // 非法的行号
            return false;
        }
    }

    /**
     * 移动到 rows 行
     * 
     * @param rows 行数 整数 表示 向后 移动 , 负数 表示 向前 移动。
     * @return
     * @throws SQLException
     */
    public boolean ops_relative(int rows) throws SQLException {
        final var _offset = this.index_of_current() + rows; // 计算新的 偏移位置
        final var row = _offset - this.index_of_first(); // 把 偏移位置转换为 行号
        return this.ops_absolute(row); // 移动 cursor 到目标 行
    }

    /**
     * 向前移动一位
     * 
     * @return
     */
    public boolean ops_previous() {
        if (this.index_of_current() >= this.index_of_first()) {
            this.relocate(this.index_of_previous()); // 偏移向前移动一步
            return true;
        } else {
            return false;
        } // if
    }

    /**
     * 向后移动一位
     * 
     * @return true if the new current row is valid; false if there are no more rows
     */
    public boolean ops_next() {
        if (this.index_of_current() < this.index_of_last()) { // 判断是否位于最后一行以前, 即 只有是 beforeLast 才存在后继，Last 和 afterLast
                                                              // 是没有后继的
            this.relocate(this.index_of_next()); // 移动数据偏移量获取当前元素
            return true;
        } else { // 非 非法索引, 即 非 beforeFirst 或是 afterLast 即 最后一行 或是 最后一行以后 就 不存在 后继 了
            this.relocate(this.index_of_after_last()); // 移动到 最后一行以后, 即 afterLast
            return false;
        } // if
    }

    /**
     * 获取当前行号
     * 
     * @return 丹玉等于1的整数
     * @throws SQLException
     */
    public int ops_get_row() throws SQLException {
        return this.index_of_current() - this.index_of_before_first();
    }

    private int index_of_before_first = -1; // before first 的 索引
    private int index_of_after_last = -1; // after last 的 索引
    private int index_of_current = index_of_before_first; // 当前的数据偏移量，初始为-1
    private IRecord current; // 当前的数据元素
    private IRecord metadata; // 元数据
    protected List<IRecord> dataset; // 数据结果集合
}
